package com.aSemy.qotwReader.core.question;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringEscapeUtils;

import com.aSemy.qotwReader.core.types.ReaderType;
import com.aSemy.qotwReader.core.utils.*;



import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.Source;
import net.htmlparser.jericho.TextExtractor;

/**
 * Used for storing metadata about the question, e.g. title, date, comments.
 * @author Adam
 *
 */
public class QuestionData
{
    /** The contents of the post used to describe the question. */
    final private String comments;
    /** The HTML source code of the comments. */
    final private Element commentsSource;
    /** The date the question was opened. */
    final private String date;
    /** The title of the question. */
    final private String title;
    /** The ebook reader to tailor the converted ebook for. */
    final private ReaderType reader;
    
    /**
     * When created it automatically extracts the data from the given HTML.
     * @param html The HTML of the Question.
     * @param reader The ebook reader to tailor the converted ebook for.
     */
    public QuestionData(QuestionHTML html, ReaderType reader)
    {
        //setInfo(html);
        commentsSource = getCommentsSource(html);
        comments = getComments(commentsSource);
        title = getTitle(commentsSource);
        date = getDate(comments);
        
        this.reader = reader;
        
        System.out.println("Title: " + title);
        System.out.println("Comments: " + comments);
        System.out.println("Date: " + date);
    }
    
    /**
     *  Gets the title in a format which is safe for use in filenames. 
     *  It does this by removing any non-word character.
     */
    public String getFilesafeTitle() { return this.title.replaceAll("\\W", ""); }
    /**
     *  Gets the date in a format which is safe for use in filenames. 
     *  It does this by removing any non-word character.
     */
    public String getFilesafeDate() { return this.date.replaceAll("\\W", ""); }

    /** Gets the title in a format with characters escaped for use in HTML. */
    public String getHtmlsafeTitle() { return StringEscapeUtils.escapeHtml(title); }
    /** Gets the date in a format with characters escaped for use in HTML. */
    public String getHtmlsafeDate() { return StringEscapeUtils.escapeHtml(date); }
    /** Gets the comments in a format with characters escaped for use in HTML. */
    public String getHtmlsafeComments() { return StringEscapeUtils.escapeHtml(comments); }

    /**
     * From the HTML this will extract and return the HTML element that contains the comments.
     * @param html The HTML of the question.
     * @return The Element that contains the comments.
     */
    private Element getCommentsSource(QuestionHTML html)
    {
        final Source source = html.getQuestionSource();
        
        Element commentsSource = null;

        for (Element e : source.getAllElements())
        {
            if (! e.isWhiteSpace() || ! e.isEmpty()) // if the element isn't just whitespace
            {
                TextExtractor t = e.getTextExtractor();
                
                // if info hasn't been assigned and it matches the element that comes before the info
                if (comments == null && t.toString().equalsIgnoreCase("Search"))// then the next one is comments
                {
                    Element next = source.getNextElement(e.getEnd());
                    TextExtractor nextText;
                    do
                    {
                        nextText = next.getTextExtractor();                        
                        commentsSource = next;                        
                        next = source.getNextElement(next.getEnd());
                    }
                    while (nextText.toString().trim().length() == 0); // while it's not a whitespace element
                    
                    return commentsSource; // that's all we need, break break break!
                }
            }
        }
        System.out.println("Error getting the source of the comments!");
        return null;
    }
    
    /**
     * Extract the comments for the question. The comments are the blurb style bit that briefly describe the question.
     * @param commentsSource The HTML source code that contains the comments.
     * @return A string containing just the text of the comments. I think Jericho converts special HTML characters.
     */
    private String getComments(Element commentsSource)
    {
        return commentsSource.getTextExtractor().toString();
    }
    
    /**
     * Extract the title of the question.
     * @param commentsSource The HTML source code that contains the title.
     * @return A string containing just the title. I think Jericho converts special HTML characters.
     */ 
    private String getTitle(Element commentsSource)
    {
        String commentsSourceText = commentsSource.toString();
        
        Pattern titlePattern = Pattern.compile("<b>(.+?)</b>");
        Matcher titleMatcher = titlePattern.matcher(commentsSourceText);
        
        if (titleMatcher.find())
            return titleMatcher.group(1);
        else
        {
            System.out.println("No title found!!!");
            return "";
        }
    }
    
    /**
     * Extract the date the question was opened. 
     * The comments string contains this, and so a regex search matches this and extracts it.
     * @param commentsSource The comments as a string
     * @return The date converted to a string by {@link CalendarUtils#getDateString(int, String, int)}.
     */ 
    private String getDate(String comments)
    {
        Pattern p = Pattern.compile("(\\w{3}) (\\d{1,2}) (\\w{3}) (\\d{4})"); // this matches the date
        Matcher m = p.matcher(comments);
        boolean match = m.find(); // is there a match?
        
        if (match)
        {
            // group zero is the whole lot
            //String day = m.group(1); // the day
            int dateInt = Integer.parseInt(m.group(2)); // the month number
            String month = m.group(3); // the month
            int yearInt = Integer.parseInt(m.group(4)); // the year

            //return CalendarUtils.getDateString(day, dateInt, month, yearInt);
            return CalendarUtils.getDateString(dateInt, month, yearInt);
        }
        else
        {
            System.out.println("No date found!!!");
            return "";
        }
    }
    
    /**
     * @return The type of reader that the ebook should be tailored for.
     */
    public ReaderType getReaderType() { return reader; }
}
